
#include "proc.h"
#include "types.h"
#include "display/main_disp.h"
#include "display/gen_disp.h"
#include "display/show_mesh_disp.h"
#include "display/compare_disp.h"
#include "display/test_disp.h"

//#include <GL/gl.h>
//#include <GL/glu.h>
#include <GL/glew.h>
#include <GL/glut.h>

// todo
#include <iostream>


void proc::idle()
{
    glutPostRedisplay();
}

void proc::visibility(int vis)
{
    active_display->visibility(vis);
}

void proc::reshape (int w, int h)
{

    params->win_width = w;
    params->win_height = h;
    
    unsigned end = menu_items.size();
    for(unsigned i=0; i<end; i++)
        menu_items[i]->reshape(w,h);
    //active_display->reshape(w,h);
    glutPostRedisplay();
}

void proc::display()
{
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    active_display->display(params->win_width, params->win_height);

    glFlush();
    glutSwapBuffers();
}

void proc::keyboard(unsigned char key, int x, int y)
{
    disp* new_active = active_display->keyboard(key,x,y);
    if(active_display != new_active) { // active display has changed
        new_active_display(active_display, new_active);
        active_display = new_active;
    }
    glutPostRedisplay();
}

void proc::keyboard_special(int key, int x, int y)
{
    // special keys do not switch the active display
    active_display->keyboard_special(key,x,y);
    glutPostRedisplay();
}

void proc::mouse(int button, int state, int x, int y)
{
    active_display->mouse(button, state, x, y);
    glutPostRedisplay();
}

void proc::motion(int x, int y)
{
    active_display->motion(x, y);
    glutPostRedisplay();
}

void proc::passive_motion(int x, int y)
{
    active_display->passive_motion(x, y);
}

void proc::gen_menu()
{
    comp_type main_menu_color[4] = {1.0,1.0,1.0,1.0};
    comp_type act_main_menu_color[4] = {0.1,1.0,0.4,1.0};

    disp* main = new main_disp(params->font, main_menu_color, act_main_menu_color,
                        params->win_width, params->win_height, params->fovy);
    disp* test = new test_disp(params->font, main_menu_color, act_main_menu_color,
                        params->win_width, params->win_height);
    disp* gen = new gen_disp(params->font, main_menu_color, act_main_menu_color,
                        params->win_width, params->win_height);
    disp* compare = new compare_disp(params->font, main_menu_color, 
                        act_main_menu_color, params->win_width, params->win_height);
    disp* show_mesh = new show_mesh_disp(params->font, main_menu_color, 
                        act_main_menu_color, params->win_width, params->win_height, params->fovy);
                        
    main->set_child(0,show_mesh);
    main->set_child(1,compare);
    main->set_child(2,gen);
    main->set_child(3,test);
    show_mesh->set_parent(main);
    compare->set_parent(main);
    gen->set_parent(main);
    test->set_parent(main);

    active_display = main;
    new_active_display(NULL, active_display);

    menu_items.push_back(main);     // the order in menu_items does not matter
    menu_items.push_back(compare);
    menu_items.push_back(gen);
    menu_items.push_back(show_mesh);
    menu_items.push_back(test);
}

void proc::del_menu()
{
    unsigned end = menu_items.size();
    for(unsigned i = 0; i<end; i++)
        delete menu_items[i];
}

inline void proc::new_active_display(disp* olddisp, disp* newdisp)
{
    if(olddisp!=NULL)
        olddisp->deinit();
    if(newdisp!=NULL)
        newdisp->init();
}

